package com.example.cinema.controller;

import com.example.cinema.entity.Result;
import com.example.cinema.entity.User;
import com.example.cinema.util.QRCodeUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.SessionAttribute;

import javax.servlet.http.HttpSession;
import javax.websocket.OnClose;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * Company 源辰信息
 *
 * @author navy
 * @date 2024/8/31
 * Email haijunzhou@hnit.edu.cn
 */
@RestController
@RequestMapping("qrcode")
@ServerEndpoint("/autoLogin/{token}")
public class QrCodeDo {

    public static final String MY_HEAD = "e:/a.png";
    @RequestMapping(path = "image", produces = MediaType.IMAGE_JPEG_VALUE)
    public void image(String content, OutputStream out) throws Exception {
        QRCodeUtil.encode(content, MY_HEAD, out, true);
    }

    @RequestMapping(path = "mobile", produces = MediaType.IMAGE_JPEG_VALUE)
    public void toMobile(OutputStream out) throws Exception {
        image("http://192.168.1.5/mobile/index.html", out);
    }

    static RedisTemplate redisTemplate;

    @Autowired
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        QrCodeDo.redisTemplate = redisTemplate;
    }

    @RequestMapping(path = "createLoginQrcode", produces = MediaType.IMAGE_JPEG_VALUE)
    public void createLoginQrcode(HttpSession session, OutputStream out) throws Exception {
        // 生成令牌 UUID
        String uuid = UUID.randomUUID().toString();
        ScanLoginInfo sli = new ScanLoginInfo(uuid, "未扫描", null);
        ValueOperations opsForValue = redisTemplate.opsForValue();
        opsForValue.set("scanLogin:" + uuid, sli, 60, TimeUnit.SECONDS);
        String content = "http://192.168.1.5/qrcode/scanLoginQrcode?token=" + uuid;
        image(content,out);
        session.setAttribute("loginToken", uuid);
    }

    @Value("${sign.session-key}")
    String sessionKey;

    @RequestMapping("scanLoginQrcode")
    public Result a(String token, HttpSession session) throws IOException {
        User user = (User) session.getAttribute(sessionKey);
        if(user == null){
            return new Result(0, "请先登录系统", null);
        }
        ValueOperations opsForValue = redisTemplate.opsForValue();
        ScanLoginInfo info = (ScanLoginInfo) opsForValue.get("scanLogin:" + token);
        if(info == null){
            return new Result(-1, "该二维码已经失效", null);
        }
        info.setStatus("扫码成功");
        info.setMyinfo(user);
        opsForValue.set("scanLogin:" + token, info, 60, TimeUnit.SECONDS);

        // TODO 通知PC前端, 扫码成功, PC要获取用户信息
        sessions.get(token).getBasicRemote().sendText("OK");

        return new Result(1, "扫码成功", null);
    }

    static HashMap<String,Session> sessions = new HashMap<>();
    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token){
        sessions.put(token, session);
        session.getUserProperties().put("token",token);
    }
    @OnClose
    public void onClose(Session session){
        String token = (String) session.getUserProperties().get("token");
        sessions.put(token, session);
    }

    @RequestMapping("autoLogin")
    public Result autoLogin(String token, HttpSession session){
        ValueOperations opsForValue = redisTemplate.opsForValue();
        ScanLoginInfo info = (ScanLoginInfo) opsForValue.get("scanLogin:" + token);
        User myinfo = info.getMyinfo();
        session.setAttribute(sessionKey, myinfo);
        return new Result(1, "登录成功!", myinfo);
    }

    @RequestMapping("getLoginToken")
    Result loginToken(@SessionAttribute(required = false) String loginToken){
        if (loginToken == null){
            return new Result(0, "登录令牌还未生成!", null);
        } else {
            return new Result(1, "登录令牌已生成!", loginToken);
        }
    }

}

@Data
@AllArgsConstructor
@NoArgsConstructor
class ScanLoginInfo implements java.io.Serializable{
    String uuid;
    String status = "未扫描";
    User myinfo;
}
